package ajjj.kiviq.facades;

import ajjj.kiviq.remoteInterfaces.IRemoteCategory;
import ajjj.kiviq.entities.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.*;

/**
 *  Updated 08-10-11 by jeklund
 *  Added a setCategories method
 * 
 *  Updated 2011-10-10 by jonatan
 *  Added a getCategory method and
 *  changed addCategory method so that it
 *  updates existing categories
 * 
 *  Updated 2011-10-11 by jeklund
 *  Bugfix: edited getCategory method so 
 *  it works when adding a new category
 * 
 *  Updated 2011-10-11 by orjohan & jeklund
 *  Added Remove method for removing Categories
 * 
 *  Updated 2011-10-11 by jonatan
 *  Fixed the add function to fully work
 *  when removing questions, etc
 * 
 * Updated 2011-10-12 by orjohan
 * Added removeCategories method if
 * user wants to remove himself from the database
 * 
 * @author orjohan
 */
@Stateless
public class CategoryFacade implements IRemoteCategory {

    @PersistenceContext(unitName = "kiviq_pu")
    private EntityManager em;

    public CategoryFacade() {
    }

    @Override
    public List<Category> getCategories(String userName) {
	try {
	    TypedQuery<UserEnt> q = em.createNamedQuery("findAllUsersWithName", UserEnt.class);
	    q.setParameter("name", userName);
	    UserEnt ue = q.getSingleResult();
	    List<Category> privateCats = new ArrayList<Category>();
	    for (Category c : ue.getCategories()) {
		privateCats.add(c);
	    }

	    return privateCats;
	} catch (Exception e) {
	    return null;
	}
    }

    @Override
    public List<Category> getPublicCategories() {

	try {
	    List<Category> publicCats = new ArrayList<Category>();
	    TypedQuery<UserEnt> q = em.createNamedQuery("findAllUsers", UserEnt.class);
	    List<UserEnt> ue = q.getResultList();
	    for (UserEnt u : ue) {
		for (Category c : u.getCategories()) {
		    if (c.isPublic()) {
			publicCats.add(c);
		    }
		}
	    }
	    return publicCats;
	} catch (Exception e) {
	    return null;
	}
    }

    @Override
    public Category getCategory(Long id) {

	if (id == null) {
	    return null;
	}

	return em.find(Category.class, id);
    }

    @Override
    public void addCategory(Category cat, String userName) {
	TypedQuery<UserEnt> tq = em.createNamedQuery("findAllUsersWithName", UserEnt.class);
	tq.setParameter("name", userName);
	UserEnt ue = tq.getSingleResult();

	Category c = getCategory(cat.getId());

	if (c == null) {
	    List<Category> list = ue.getCategories();
	    list.add(cat);
	} else {
	    c.setTitle(cat.getTitle());
	    //This is very ugly, but can't seem to persist
	    //without doing it like this
	    c.getQuestions().clear();
	    for (Question q : cat.getQuestions()) {
		c.addQuestion(q);
	    }
	    c.setPublic(cat.isPublic());
	}

	em.persist(ue);
    }

    @Override
    public void removeCategory(Category cat, String user) {

	TypedQuery<UserEnt> q = em.createNamedQuery("findAllUsersWithName", UserEnt.class);
	q.setParameter("name", user);
	UserEnt ue = q.getSingleResult();

	List<Category> cats = getCategories(user);

	Iterator<Category> it = cats.iterator();

	while (it.hasNext()) {
	    if (it.next().getId() == cat.getId()) {
		it.remove();
	    }
	}

	ue.setCategories(cats);

	em.merge(ue);
	em.remove(em.merge(cat));
    }

    @Override
    public void removeCategories(String user) {

	TypedQuery<UserEnt> q = em.createNamedQuery("findAllUsersWithName", UserEnt.class);
	q.setParameter("name", user);
	UserEnt ue = q.getSingleResult();

	List<Category> userCats = getCategories(user);
	List<Category> cats = new ArrayList<Category>();

	ue.setCategories(cats);

	em.merge(ue);
	for (Category c : userCats) {
	    em.remove(c);
	}
    }
}
